博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用户角色权限 案例
阅读量:4876 次
发布时间:2019-06-11

本文共 20932 字,大约阅读时间需要 69 分钟。

#权限管理:rbac:role basic access control         # 一 根据用户获取权限, session中 中间件实现权限控制         # 二 菜单管理           #默认展开           #只显示当前用户菜单

一、权限用户表

a:SQL表结构

from django.db import models# Create your models here.class User(models.Model):    """    用户表    """    username = models.CharField(verbose_name='用户名', max_length=32)    password = models.CharField(verbose_name='密码', max_length=64)    email = models.EmailField(verbose_name='邮箱')    def __str__(self):        return self.usernameclass Role(models.Model):    """    角色表    """    caption = models.CharField(verbose_name='角色', max_length=32)    def __str__(self):        return self.captionclass User2Role(models.Model):    """    用户角色关系表    """    user = models.ForeignKey(User, verbose_name='用户', related_name='roles')    role = models.ForeignKey(Role, verbose_name='角色', related_name='users')    def __str__(self):        return '%s-%s' % (self.user.username, self.role.caption,)class Menu(models.Model):    """    菜单表    """    caption = models.CharField(verbose_name='菜单名称', max_length=32)    parent = models.ForeignKey('self', verbose_name='父菜单', related_name='p', null=True, blank=True)    def __str__(self):        prev = ""        parent = self.parent        while True:            if parent:                prev = prev + '-' + str(parent.caption)                parent = parent.parent            else:                break        return '%s-%s' % (prev, self.caption,)class Permission(models.Model):    """    权限    """    caption = models.CharField(verbose_name='权限', max_length=32)    url = models.CharField(verbose_name='URL正则', max_length=128)    menu = models.ForeignKey(Menu, verbose_name='所属菜单', related_name='permissions',null=True,blank=True)    def __str__(self):        return "%s-%s" % (self.caption, self.url,)class Action(models.Model):    """    操作:增删改查    """    caption = models.CharField(verbose_name='操作标题', max_length=32)    code = models.CharField(verbose_name='方法', max_length=32)    def __str__(self):        return self.captionclass Permission2Action2Role(models.Model):    """    权限操作关系表    """    permission = models.ForeignKey(Permission, verbose_name='权限URL', related_name='actions')    action = models.ForeignKey(Action, verbose_name='操作', related_name='permissions')    role = models.ForeignKey(Role, verbose_name='角色', related_name='p2as')    class Meta:        unique_together = (            ('permission', 'action', 'role'),        )    def __str__(self):        return "%s-%s-%s" % (self.permission, self.action, self.role,)
models.py

b.输出菜单

urlpatterns = [    url(r'^auth-menu.html$',view2.menu),]
url.py
from django.contrib import admin# Register your models here.from app02 import modelsadmin.site.register(models.User)admin.site.register(models.Role)admin.site.register(models.User2Role)admin.site.register(models.Menu)admin.site.register(models.Permission)admin.site.register(models.Action)admin.site.register(models.Permission2Action2Role)
app02/admin.py
def menu(request):   """    需要用户名或用户ID,产出:用户关联所有菜单    :param request:    :return:    """    # 所有菜单:处理成当前用关联的菜单    all_menu_list = models.Menu.objects.all().values('id', 'caption', 'parent_id')    """    [        {'id':1, 'caption':'菜单1', parent_id:None},        {'id':2, 'caption':'菜单2', parent_id:None},        {'id':3, 'caption':'菜单3', parent_id:None},        {'id':4, 'caption':'菜单1-1', parent_id:1},    ]    {        1:{'id':1, 'caption':'菜单1', parent_id:None,status:False,opened:False,child:[]},        2:{'id':2, 'caption':'菜单2', parent_id:None,status:False,opened:False,child:[]},        3:{'id':3, 'caption':'菜单3', parent_id:None,status:False,opened:False,child:[]},        5:{'id':4, 'caption':'菜单1-1', parent_id:1,status:False,opened:False,child:[]},    }   """    user = models.User.objects.filter(username='alex').first()    role_list = models.Role.objects.filter(users__user=user)    permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__id',                                                                                              'permission__url',                                                                                              'permission__menu_id',                                                                                              'permission__caption').distinct()    """    [        {'permission__url':'/order.html','permission__caption': '订单管理','permission__menu_id': 1 },        {'permission__url':'/order.html','permission__caption': '订单管理','permission__menu_id': 2 },        {'permission__url':'/order.html','permission__caption': '订单管理','permission__menu_id': 3 },        {'permission__url':'/order.html','permission__caption': '订单管理','permission__menu_id': 4 },    ]    """    ##### 将权限挂靠到菜单上 ########    all_menu_dict = {}    for row in all_menu_list:        row['child'] = []  # 添加孩子        row['status'] = False  # 是否显示菜单        row['opened'] = False  # 是否默认打开        all_menu_dict[row['id']] = row    for per in permission_list:        if not per['permission__menu_id']:            continue        item = {            'id': per['permission__id'],            'caption': per['permission__caption'],            'parent_id': per['permission__menu_id'],            'url': per['permission__url'],            'status': True,            'opened': False        }        # print(item["url"])        if re.match(per['permission__url'],request.path_info):        # if re.match(per['permission__url'], "/orders.html"):            item['opened'] = True        pid = item['parent_id']        all_menu_dict[pid]['child'].append(item)        # 将当前权限前辈status=True        temp = pid  # 1.父亲ID        while not all_menu_dict[temp]['status']:            all_menu_dict[temp]['status'] = True            temp = all_menu_dict[temp]['parent_id']            if not temp:                break        # 将当前权限前辈opened=True        if item['opened']:            temp1 = pid  # 1.父亲ID            while not all_menu_dict[temp1]['opened']:                all_menu_dict[temp1]['opened'] = True                temp1 = all_menu_dict[temp1]['parent_id']                if not temp1:                    break    # ############ 处理菜单和菜单之间的等级关系 ############    """    all_menu_dict = {        1:{'id':1, 'caption':'菜单1', parent_id:None,status:False,opened:False,child:[{'permission__url':'/order.html','permission__caption': '订单管理','permission__menu_id': 1 },]},        2:{'id':2, 'caption':'菜单2', parent_id:None,status:False,opened:False,child:[]},        3:{'id':3, 'caption':'菜单3', parent_id:None,status:False,opened:False,child:[]},        5:{'id':4, 'caption':'菜单1-1', parent_id:1,status:False,opened:False,child:[]},    }    all_menu_list= [        {'id':1, 'caption':'菜单1', parent_id:None,status:False,opened:False,child:[{'permission__url':'/order.html','permission__caption': '订单管理','permission__menu_id': 1 }, {'id':4, 'caption':'菜单1-1', parent_id:1,status:False,opened:False,child:[]},]},        {'id':2, 'caption':'菜单2', parent_id:None,status:False,opened:False,child:[]},        {'id':3, 'caption':'菜单3', parent_id:None,status:False,opened:False,child:[]},    ]    """    result = []    for row in all_menu_list:        pid = row['parent_id']        if pid:            all_menu_dict[pid]['child'].append(row)        else:            result.append(row)    ##################### 结构化处理结果 #####################    # print(result)    # for row in result:    #     # print(row['caption'], row['status'], row['opened'], )    #     print(row)    ##################### 通过结构化处理结果,生成菜单开始 #####################    def menu_tree(menu_list):        tpl1 = """        
""" tpl2 = """ {2} """ menu_str = "" for menu in menu_list: if not menu['status']: continue # menu: 菜单,权限(url) if menu.get('url'): # 权限 menu_str += tpl2.format(menu['url'],'active' if menu['opened'] else "",menu['caption']) else: # 菜单 if menu['child']: child_html = menu_tree(menu['child']) else: child_html = "" menu_str += tpl1.format(menu['caption'], child_html,"" if menu['opened'] else 'hide') return menu_str menu_html = menu_tree(result) return render(request, "menu_html.html", {
"menu_html":menu_html})
app02/views.py
    
Title {
{ menu_html|safe }}
menu_html

c.result 结果递归 debug调试

result =    [    {'opened': True, 'parent_id': None, 'caption': '菜单一', 'id': 1, 'status': True,        'child': [                {'opened': False, 'parent_id': 1, 'caption': '帅哥管理', 'id': 5, 'status': True, 'url': '/shuaige.html'},                {'opened': True, 'parent_id': 1, 'caption': '菜单一  一', 'id': 4, 'status': True,                    'child': [                        {'opened': True, 'parent_id': 4, 'caption': '用户管理', 'id': 1, 'status': True, 'url': '/users.html'},                        {'opened': False, 'parent_id': 4, 'caption': '订单管理', 'id': 2, 'status': True, 'url': '/orders.html'}                    ]                },                {'opened': False, 'parent_id': 1, 'caption': '菜单一 二', 'id': 5, 'status': False, 'child': []},                {'opened': False, 'parent_id': 1, 'caption': '菜单一  三', 'id': 6, 'status': False, 'child': []}            ]    },    {'opened': False, 'parent_id': None, 'caption': '菜单二', 'id': 2, 'status': False, 'child': []},    {'opened': False, 'parent_id': None, 'caption': '菜单三', 'id': 3, 'status': False, 'child': []}    ] 
result = [{
'opened': True, 'parent_id': None, 'caption': '菜单一', 'id': 1, 'status': True, 'child': [{
'opened': False, 'parent_id': 1, 'caption': '帅哥管理', 'id': 5, 'status': True, 'url': '/shuaige.html'}, {
'opened': True, 'parent_id': 1, 'caption': '菜单一 一', 'id': 4, 'status': True, 'child': [{
'opened': True, 'parent_id': 4, 'caption': '用户管理', 'id': 1, 'status': True, 'url': '/users.html'}, {
'opened': False, 'parent_id': 4, 'caption': '订单管理', 'id': 2, 'status': True, 'url': '/orders.html'}]}, {
'opened': False, 'parent_id': 1, 'caption': '菜单一 二', 'id': 5, 'status': False, 'child': []}, {
'opened': False, 'parent_id': 1, 'caption': '菜单一 三', 'id': 6, 'status': False, 'child': []}]}, {
'opened': False, 'parent_id': None, 'caption': '菜单二', 'id': 2, 'status': False, 'child': []}, {
'opened': False, 'parent_id': None, 'caption': '菜单三', 'id': 3, 'status': False, 'child': []}]def menu_tree(menu_list): tpl1 = """
""" tpl2 = """ {2} """ menu_str = "" for menu in menu_list: if not menu['status']: continue # menu: 菜单,权限(url) if menu.get('url'): # 权限 menu_str += tpl2.format(menu['url'], 'active' if menu['opened'] else "", menu['caption']) print("***", menu_str) else: # 菜单 if menu['child']: child_html = menu_tree(menu['child']) print("----", child_html) else: child_html = "" print("111") menu_str += tpl1.format(menu['caption'], child_html, "" if menu['opened'] else 'hide') print("AAAAA", menu_str) print(123) return menu_strmenu_html = menu_tree(result)print("xx", menu_html)

二、组件

生成公共app       - 权限限制       - 生成菜单
python3 manage.py startapp rbac  

配置文件:

复制代码#白名单url, 不验证VALID_URL = [    '/app01/.*',    '/app02/.*'    '/login.html'    '/logout.html']
config.py

rbac models:

from django.db import modelsclass User(models.Model):    """    用户表    """    username = models.CharField(verbose_name='用户名', max_length=32)    password = models.CharField(verbose_name='密码', max_length=64)    email = models.EmailField(verbose_name='邮箱')    def __str__(self):        return self.usernameclass Role(models.Model):    """    角色表    """    caption = models.CharField(verbose_name='角色', max_length=32)    def __str__(self):        return self.captionclass User2Role(models.Model):    """    用户角色关系表    """    user = models.ForeignKey(User, verbose_name='用户', related_name='roles')    role = models.ForeignKey(Role, verbose_name='角色', related_name='users')    def __str__(self):        return '%s-%s' % (self.user.username, self.role.caption,)class Menu(models.Model):    """    菜单表    """    caption = models.CharField(verbose_name='菜单名称', max_length=32)    parent = models.ForeignKey('self', verbose_name='父菜单', related_name='p', null=True, blank=True)    def __str__(self):        prev = ""        parent = self.parent        while True:            if parent:                prev = prev + '-' + str(parent.caption)                parent = parent.parent            else:                break        return '%s-%s' % (prev, self.caption,)class Permission(models.Model):    """    权限    """    caption = models.CharField(verbose_name='权限', max_length=32)    url = models.CharField(verbose_name='URL正则', max_length=128)    menu = models.ForeignKey(Menu, verbose_name='所属菜单', related_name='permissions',null=True,blank=True)    def __str__(self):        return "%s-%s" % (self.caption, self.url,)class Action(models.Model):    """    操作:增删改查    """    caption = models.CharField(verbose_name='操作标题', max_length=32)    code = models.CharField(verbose_name='方法', max_length=32)    def __str__(self):        return self.captionclass Permission2Action2Role(models.Model):    """    权限操作关系表    """    permission = models.ForeignKey(Permission, verbose_name='权限URL', related_name='actions')    action = models.ForeignKey(Action, verbose_name='操作', related_name='permissions')    role = models.ForeignKey(Role, verbose_name='角色', related_name='p2as')    class Meta:        unique_together = (            ('permission', 'action', 'role'),        )    def __str__(self):        return "%s-%s-%s" % (self.permission, self.action, self.role,)
models.py

中间件认证  

#验证中间件from django.utils.deprecation import MiddlewareMixinfrom django.shortcuts import HttpResponsefrom rbac import configimport reclass RbacMiddleware(MiddlewareMixin):    def process_request(self,request,*args,**kwargs):        for pattern in config.VALID_URL:            if re.match(pattern,request.path_info):                return None        action = request.GET.get('md') # GET        user_permission_dict = request.session.get('user_permission_dict')        if not user_permission_dict:            return HttpResponse('无权限')        # action_list = user_permission_dict.get(request.path_info)        flag = False        for k,v in user_permission_dict.items():            if re.match(k,request.path_info):                if action in v:                    flag = True                    break        if not flag:            return HttpResponse('无权限')
/middleware/md.py

后端代码

import refrom rbac import modelsfrom django.utils.safestring import mark_safedef permission_session(user_id,request):    """    :param user_id:  rbac中的user表中一条数据id    :param request:    :return:    """    # obj = models.User.objects.filter(username='杨明').first()    #    # # x = models.User2Role.objects.filter(user_id=obj.id)    # # [User2Role,User2Role,User2Role]    #    # role_list = models.Role.objects.filter(users__user_id=obj.id)    # # [Role,]    # from django.db.models import Count    # # permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__url','action__code').annotate(c=Count('id'))    # permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__url','action__code').distinct()    """    [        {permission_url: '/index.html', action_code:'GET'},        {permission_url: '/index.html', action_code:'POST'},        {permission_url: '/index.html', action_code:'DEL'},        {permission_url: '/index.html', action_code:'Edit'},        {permission_url: '/order.html', action_code:'GET'},        {permission_url: '/order.html', action_code:'POST'},        {permission_url: '/order.html', action_code:'DEL'},        {permission_url: '/order.html', action_code:'Edit'},    ]    放在Session中    /index.html?md=GET    {        '/index.html': [GET,POST,DEL,Edit],        '/order.html': [GET,POST,DEL,Edit],    }    """    user_permission_dict = {        '/ah-index.html': ["GET","POST","DEL","Edit"],        '/order.html':  ["GET","POST","DEL","Edit"],        '/index-(\d+).html':  ["GET","POST","DEL","Edit"],    }    request.session['user_permission_dict'] = user_permission_dictdef menu(user_id,current_url):    """    根据用户ID,当前URL:获取用户所有菜单以及权限,是否显示,是否打开    :param user_id:    :param current_url:    :return:    """    # 所有菜单:处理成当前用关联的菜单    all_menu_list = models.Menu.objects.all().values('id','caption','parent_id')    user = models.User.objects.filter(id=user_id).first()    role_list = models.Role.objects.filter(users__user=user)    permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).values('permission__id','permission__url','permission__menu_id','permission__caption').distinct()    ##### 将权限挂靠到菜单上 ########    all_menu_dict = {}    for row in all_menu_list:        row['child'] = []      # 添加孩子        row['status'] = False # 是否显示菜单        row['opened'] = False # 是否默认打开        all_menu_dict[row['id']] = row    for per in permission_list:        if not per['permission__menu_id']:            continue        item = {            'id':per['permission__id'],            'caption':per['permission__caption'],            'parent_id':per['permission__menu_id'],            'url': per['permission__url'],            'status': True,            'opened': False        }        if re.match(per['permission__url'],current_url):            item['opened'] = True        pid = item['parent_id']        all_menu_dict[pid]['child'].append(item)        # 将当前权限前辈status=True        temp = pid # 1.父亲ID        while not all_menu_dict[temp]['status']:            all_menu_dict[temp]['status'] = True            temp = all_menu_dict[temp]['parent_id']            if not temp:                break        # 将当前权限前辈opened=True        if item['opened']:            temp1 = pid # 1.父亲ID            while not all_menu_dict[temp1]['opened']:                all_menu_dict[temp1]['opened'] = True                temp1 = all_menu_dict[temp1]['parent_id']                if not temp1:                    break    # ############ 处理菜单和菜单之间的等级关系 ############    result = []    for row in all_menu_list:        pid = row['parent_id']        if pid:            all_menu_dict[pid]['child'].append(row)        else:            result.append(row)    ##################### 结构化处理结果 #####################    for row in result:        print(row['caption'],row['status'],row['opened'],row)    def menu_tree(menu_list):        tpl1 = """        
""" tpl2 = """ {2} """ menu_str = "" for menu in menu_list: if not menu['status']: continue # menu: 菜单,权限(url) if menu.get('url'): # 权限 menu_str += tpl2.format(menu['url'],'active' if menu['opened'] else "",menu['caption']) else: # 菜单 if menu['child']: child_html = menu_tree(menu['child']) else: child_html = "" menu_str += tpl1.format(menu['caption'], child_html,"" if menu['opened'] else 'hide') return menu_str menu_html = menu_tree(result) return menu_html# simple_tagdef css(): v = """ """ return v# simple_tagdef js(): v = """ """ return v
service.py

a:封装以后调用

加入中间件

#自定义的中间件加入到settingMIDDLEWARE = [    'django.middleware.security.SecurityMiddleware',    'django.contrib.sessions.middleware.SessionMiddleware',    'django.middleware.common.CommonMiddleware',    'django.middleware.csrf.CsrfViewMiddleware',    'django.contrib.auth.middleware.AuthenticationMiddleware',    'django.contrib.messages.middleware.MessageMiddleware',    'django.middleware.clickjacking.XFrameOptionsMiddleware',    'rbac.middleware.md.RbacMiddleware',    ]
setting.py
#后端from rbac import service 1. 用户登录后,拿到用户的ID,调用permission_session()函数(函数代码还没写)   函数获取用户角色的权限,格式如:   “”“    user_permission_dict = {        '/ah-index.html': ["GET","POST","DEL","Edit"],        '/order.html':  ["GET","POST","DEL","Edit"],        '/index-(\d+).html':  ["GET","POST","DEL","Edit"],    }   ”“”     def login():      permission_session(用户ID,request)      return ..... 2.setting中加入中间件,如上   3.#获取菜单    current_url= request.pathinfo    menu_list = service.menu(用户ID,current_url) 4.尽量用simple_tag    css = servicr.css()    js = servicr.js() 5.前端     {
{ css|safe }} {
{ menu_list|safe }} {
{ js|safe }}  

  

 

转载于:https://www.cnblogs.com/niejinmei/p/7227539.html

你可能感兴趣的文章
实时Web与WebSocket实践
查看>>
Equals()和GetHashCode()方法深入了解
查看>>
实验9(1)程序填空:下列程序在数组中同时查找最大元素和最小元素的下标,分别存放在 main()函数的max 和 min 变量中。要求:根据运行结果分析程序和填空,并注释说明填充依据。...
查看>>
Adobe Flex迷你教程 — ActionScript实现二维向量运算
查看>>
物联网架构成长之路(10)-Nginx负载均衡
查看>>
equals()重写
查看>>
python matplotlib 简单生成图
查看>>
[导入]终于搞定笔记本的待机
查看>>
maven 配置问题
查看>>
图片视频访问servlet(支持苹果视频断点续传)
查看>>
视图的创建、查询与更新
查看>>
WCF小试
查看>>
js兼容各个浏览器的复制功能
查看>>
数字反转
查看>>
Unique Binary Search Trees II
查看>>
素数筛选-hdu2710
查看>>
WebService 生成客户端
查看>>
VxWorks嵌入式系统几种常用的延时方法 分类: vxWorks ...
查看>>
Swagger使用总结
查看>>
powershell 删除7天前的文件
查看>>